#include "symbol_table.h"
#include <stdlib.h>
#include <string.h>

Scope* current_scope = NULL;

void enter_scope() {
    Scope* new_scope = malloc(sizeof(Scope));
    new_scope->symbols = NULL;
    new_scope->parent = current_scope;
    current_scope = new_scope;
}

void exit_scope() {
    if (current_scope == NULL) {
        fprintf(stderr, "Error: Attempted to exit a NULL scope.\n");
        return;
    }

    Scope* old_scope = current_scope;
    current_scope = old_scope->parent;  // 先更新当前作用域到父作用域

    // 释放当前作用域的符号表
    Symbol* current_symbol = old_scope->symbols;
    while (current_symbol != NULL) {
        Symbol* next_symbol = current_symbol->next;
        // free_type(current_symbol->type_info);  // 释放类型信息
        // free(current_symbol->name);            // 释放符号名称
        // free(current_symbol);                  // 释放符号本身
        current_symbol = next_symbol;
    }

    free(old_scope);  // 最后释放作用域结构体

    // printf("%d, Current scope is now: %p |\n",57 ,current_scope);
}

void add_symbol(char* name, SymbolType type, Type* type_info, int lineno) {
    if (check_symbol_conflict(name)) {
        // 错误处理已在check中完成
        return;
    }
    
    Symbol* new_sym = malloc(sizeof(Symbol));
    new_sym->name = strdup(name);
    new_sym->type = type;
    new_sym->lineno = lineno;
    new_sym->type_info = type_info;
    new_sym->next = current_scope->symbols;
    current_scope->symbols = new_sym;
}

Symbol* find_symbol(char* name) {
    Scope* scope = current_scope;

    // printf("%d, %s |\n",36 ,name);

    /* if(scope->symbols == NULL) printf("%d, %s |\n",37 ,"current_scope->symbols is NULL!!!");
    else {
        // printf("%d, %s |\n",39 ,scope->symbols->next->name);
    } */

    while (scope) {
        Symbol* sym = scope->symbols;
        while (sym) {

            // printf("%d, %s |\n",38 ,sym->name);

            if (strcmp(sym->name, name) == 0) {
                return sym;
            }
            sym = sym->next;
        }
        scope = scope->parent;
    }
    return NULL;
}

int check_symbol_conflict(char* name) {
    Symbol* existing = find_symbol(name);
    if (existing) {
        /* fprintf(stderr, "Error type 3 at Line %d: Redefined symbol '%s'\n", 
               existing->lineno, name); */
        return 1;
    }
    return 0;
}

void free_type(Type* type) {
    if (!type) return;
    switch (type->kind) {
        case ARRAY:
            free_type(type->array.elem);
            break;
        case STRUCTURE:
            free(type->structure.name);
            Symbol* field = type->structure.fields;
            while (field) {
                Symbol* next = field->next;
                free_type(field->type_info);
                free(field->name);
                free(field);
                field = next;
            }
            break;
        case FUNCTION:
            free_type(type->function.ret);
            Symbol* param = type->function.params;
            while (param) {
                Symbol* next = param->next;
                free_type(param->type_info);
                free(param->name);
                free(param);
                param = next;
            }
            break;
        default:
            break;
    }
    free(type);
}